package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.common.query.ScenicDetailQueryObject;
import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.repository.ScenicCommentTemplateRepository;
import cn.wolfcode.luowowo.search.service.IScenicCommentSearchService;
import cn.wolfcode.luowowo.search.service.ISearchService;
import cn.wolfcode.luowowo.search.template.ScenicCommentTemplate;
import com.alibaba.fastjson.JSON;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.dubbo.config.annotation.Service;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.ArrayList;
import java.util.List;

@Service
public class ScenicCommentSearchServiceImpl implements IScenicCommentSearchService {
    @Autowired
    private ScenicCommentTemplateRepository scenicCommentTemplateRepository;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Override
    public Page<ScenicCommentTemplate> query(ScenicDetailQueryObject qo) {

        setKeyword(qo);

        Page<ScenicCommentTemplate> comment = hightLightSearch(ScenicCommentTemplate.INDEX_TYPE_NAME,
                ScenicCommentTemplate.class, qo, "comment");
        return comment;
    }

    public void save(ScenicCommentTemplate template) {
        ScenicCommentTemplate save = scenicCommentTemplateRepository.save(template);
        System.out.println(save);
    }

    private ScenicDetailQueryObject setKeyword(ScenicDetailQueryObject qo) {
        // 178487584  标志性建筑
        // 103125314  人很多
        // 183864017   值得去
        // 104277092  恐高
        // 176664633  交通方便
        switch (qo.getCategory()) {
            case 178487584:
                qo.setKeyword("标志性建筑");
                break;
            case 103125314:
                qo.setKeyword("人很多");
                break;
            case 183864017:
                qo.setKeyword("值得去");
                break;
            case 104277092:
                qo.setKeyword("恐高");
                break;
            case 176664633:
                qo.setKeyword("交通方便");
                break;
        }
        return qo;
    }

    public <T> Page<T> hightLightSearch(String indexAndType, Class<T> clz, ScenicDetailQueryObject qo, String... fields) {
        String preTag = "<span style='background-color: yellow'>";
        String postTag = "</span>";

        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withIndices(indexAndType).withTypes(indexAndType);

        HighlightBuilder.Field[] fs = new HighlightBuilder.Field[fields.length];
        for (int i = 0; i < fields.length; i++) {
            fs[i] = new HighlightBuilder.Field(fields[i])
                    .preTags(preTag).postTags(postTag);
        }

        builder.withQuery(QueryBuilders.boolQuery().must(QueryBuilders.multiMatchQuery(qo.getKeyword(), fields))
                .must(QueryBuilders.termQuery("scenicId", qo.getScenicId())));
        builder.withHighlightFields(fs);
        builder.withPageable(PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize()));

        return elasticsearchTemplate.queryForPage(builder.build(), clz, new SearchResultMapper() {
            public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
                List<T> content = new ArrayList<>();

                try {
                    for (SearchHit hit : response.getHits().getHits()) {
                        T obj = JSON.parseObject(hit.getSourceAsString(), clazz);

                        for (HighlightField field : hit.getHighlightFields().values()) {
                            String name = field.getName();
                            Text text = field.getFragments()[0];
                            BeanUtils.setProperty(obj, name, text);
                        }

                        content.add(obj);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
                return new AggregatedPageImpl<>(content, pageable, response.getHits().totalHits);
            }
        });
    }


}
